package src.stateMachine;

import java.util.Hashtable;
import java.util.LinkedList;

import src.Ks;



public class StateMachine {

	
	//Todos los estados que se declaran (haciendo new de la clase que representa al estado) se guardan en una hashtable para poder ser
	//seteado automaticamente en el update de la maquina de estado:
	public static Hashtable s_states = null;
	//El hash cuenta con : 
	//Objeto estado al cual hacerle init, update, paint, destroy
	//Key que representa el estado, que es un Integer con un id unico.
	
	
	//Manual de uso:
	//Los estado se declaran haciendo : EstadoX nombre = new EstadoX (en cualquier parte)
	//StateMachine.setInitialState(EstadoX.key)
	//StateMachine.setNextState(EstadoX.key) le pasamos el key perteneciente al estado para que lo busque en el hash.
	//StateMachine.goToPreviousState() 
	
	public static Statizable s_nextState = null;
	public static Statizable s_currentState = null;
	public static Statizable s_prevState = null;

	
    public static boolean DBG = false;
	
	public StateMachine(){
		s_states = new Hashtable();

		init();
	}
	
	
	public static void init(){
		
		s_states = new Hashtable();
		
		
		createStates();
		
		
		if (Ks.DBG && Ks.DBG_SM){
			System.out.println("DBG: " + "StateMachine Inicializada...");
		}
	}

	public static void createStates(){
		//		defino aca los estados que voy a usar, aunque con esta implementacion podria definirlos en cualquier lado:
		new StateGame();
		new StateMenu();
		new StateUpdateInput();
		//TODO: ver como se comporta si hago new del mismo estado dos veces, y fixearlo si se rompe (hacer un singleton) no deberia romperse :S
		
		//estoy obligado a setear un estado inicial sino se rompe todo...
		setInitialState(StateMenu.key);
	}
	
	//para agregar un estado agrego un objeto que implemente Statizable y un Objeto Integer que lo represente:
	public static boolean addState(Statizable s, Integer key){
		
		
		if (s_states.containsKey(key) || s_states.containsValue(s)){
			return false;
		}
		s_states.put(key, s);
		return true;
	}
	
	public static boolean goToPreviousState(){
		if (s_prevState != null){
			s_currentState = s_prevState;
			return true;
		}
		
		return false;
	}
	
	public static boolean setNextState(Object key){
		
		if (s_states.containsKey(key)){
			
			s_nextState =  (Statizable) s_states.get(key);
			if (Ks.DBG && Ks.DBG_SM){
				System.out.println("DBG: " + "State con key: " + key.toString() + " seteado como nextState...");
			}
			return true;
		}
		
		if (Ks.DBG && Ks.DBG_SM){
			System.out.println("DBG: " + "State con key: " + key.toString() + " No se puso setear como nextState...");
		}
		
		return false;
	}
	
	public static boolean setInitialState(Integer key){
		if (s_states.containsKey(key)){
			
			s_currentState =  (Statizable) s_states.get(key);
			if (Ks.DBG && Ks.DBG_SM){
				System.out.println("DBG: " + "State con key: " + key.toString() + " seteado como currentState...");
			}
			return true;
		}
		
		if (Ks.DBG && Ks.DBG_SM){
			System.out.println("DBG: " + "State con key: " + key.toString() + " No se puso setear como nextState...");
		}
		
		return false;
	}
	//public static int s_currentState;
	
	//update del estado actual:
	public static void update(){
	
		if (Ks.DBG && Ks.DBG_SM){
			System.out.println("DBG: " + "update StateMachine...");
			System.out.println("currentState: " + s_currentState);
			System.out.println("nextState: " + s_nextState);
		}
		
		
		s_currentState.update();
		
		s_currentState.paint();
			
		
		//cambio de estado
		if (s_nextState != null){
			
			s_currentState.destroy();
			
			s_prevState = s_currentState;
			
			s_currentState = s_nextState;
			
			s_nextState = null;
			
			s_currentState.init();
			
			
			if (Ks.DBG && Ks.DBG_SM){
				
				System.out.println("DBG: " + "cambio de estado exitoso: " + "currentState: " + s_currentState);
			}
		}
		
	}
	


}
